parser grammar CParser;

options {
  language = Java;
  tokenVocab = CLexer;
}

@header {
    package es.etsii.pl.P6_Flexer;
}

entrada: (include)* (function_def)+ EOF ;

include: NUMBERSIGN INCLUDETOK (LESS ID (DOT ID)? GREATER | CADENA);
statement: (if_statement | while_statement | var_definition | (expression QUESTION) => if_aritm | action);
action: (asignacion | incdec | RETURN (ID | numero)? | function_statement | BREAK) SEMICOLON;

//definicion funcion 
function_def: tipo ID LPARENTHESIS (params_def | VOID)? RPARENTHESIS 
          LCURLY (statement)+ RCURLY;

bool: TRUE | FALSE;
numero: (MINUS)? (NUM_INTEGER | NUM_REAL);
incdec: ID (INC | DEC); 
asignacion: ID ASSIGN valor;
valor: (TRUE | FALSE) => bool | CARACTER | CADENA | valor2;
valor2: (ID LPARENTHESIS) => function_statement | expression;

exp : exp_mult ((PLUS | MINUS) exp_mult)* ;
exp_mult : exp_base ((ASTERISK | DIV) exp_base)* ;
exp_base : (numero | ID) | LPARENTHESIS exp RPARENTHESIS;

if_statement: IF LPARENTHESIS expression RPARENTHESIS (LCURLY (statement)+ RCURLY | statement) ; // ej: 2 * a <= b, ej: true
expression: (simple_logic (operator_logico)*) => exp_logico | exp_comparar;
exp_comparar: exp (operator_comparar exp)?; //exp puede derivar en solo ID
exp_logico: simple_logic (operator_logico simple_logic)*; 
simple_logic: (NOT)? (bool | ID) | LPARENTHESIS exp_logico RPARENTHESIS | function_statement; 
operator_comparar: LESS | GREATER | NOTEQUAL | LESSEQUAL | GREATEQUAL; //< > == <= >= 
operator_logico: AND | OR;

while_statement: WHILE LPARENTHESIS expression RPARENTHESIS LCURLY (statement)+ RCURLY;
if_aritm: expression QUESTION valor COLON valor SEMICOLON;

var_definition: tipo (ASTERISK)? ID (COMMA ID)* (ASSIGN valor)? SEMICOLON; //ej.: int * a, b;
tipo: INT | CHAR | FLOAT | DOUBLE | STRING | VOID;
   
   
//statement funcion
function_statement: ID LPARENTHESIS (params_statement)? RPARENTHESIS;
params_statement: param_stat (COMMA param_stat)*;
param_stat: ID (LBRACKET NUM_INTEGER RBRACKET)? | CADENA; //ej.: yyin = fopen(argv[1], "r");


params_def: def_par (COMMA def_par)*;
def_par: tipo (ASTERISK)? ID (LBRACKET RBRACKET)?;
